﻿using System;
using System.Collections.Specialized;
using System.Linq;
using System.Windows.Forms;

namespace MinecraftBackupAssistant.Forms
{
    public partial class SettingsForm : Form
    {
        bool unsavedChanges = false;
        public event Action SettingsUpdated;

        StringCollection timestamps;
        ToolTip tip;

        public SettingsForm()
        {
            InitializeComponent();
        }

        private void SettingsForm_Load(object sender, EventArgs e)
        {
            if (!Properties.Settings.Default.SettingsEdited)
            {
                backupLocationTextBox.BorderStyle = BorderStyle.FixedSingle;
                backupLocationTextBox.BackColor = System.Drawing.Color.Red;
                backupLocationTextBox.ForeColor = System.Drawing.Color.White;
            }

            #region General
            exeLocationTextBox.Text = Properties.Settings.Default.EXEPath;
            backupLocationTextBox.Text = Properties.Settings.Default.BackupPath;
            mapperTextBox.Text = Properties.Settings.Default.MapperPath;
            minecraftPortableTextBox.Text = Properties.Settings.Default.MinecraftPortablePath;
            minecraftPortableCheckbox.Checked = Properties.Settings.Default.MinecraftPortablePath != "";
            updatesCheckBox.Checked = Properties.Settings.Default.CheckForUpdates;
            #endregion

            #region Backup
            backupsToKeepTextBox.Text = Properties.Settings.Default.NumberBackupsToKeep.ToString();
            zipCheckBox.Checked = Properties.Settings.Default.ShouldZip;
            mapperCheckBox.Checked = Properties.Settings.Default.ShouldMap;
            unsavedChanges = false;
            #endregion

            #region Timestamps
            timestamps = Properties.Settings.Default.Timestamps.Clone<StringCollection>();
            loadDateTimeFormatComboBox();
            #endregion

            #region Mapper
            loadMapperSettings();
			ToolTip toolTip = new ToolTip();
            #endregion

            unsavedChanges = false;
        }

		private void renderCavesCheckBox_CheckedChanged(object sender, EventArgs e)
		{
			renderBlendedCheckBox.Enabled = renderCavesCheckBox.Checked;
		}

        private void Settings_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (unsavedChanges == true)
            {
                DialogResult result = MessageBox.Show("You have made changes to the settings. Do you want to save before you return to the main form?", "Save Changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                if (result == DialogResult.Yes)
                    e.Cancel = !saveSettings();
                else if (result == DialogResult.Cancel)
                    e.Cancel = true;
                else if (result == DialogResult.No)
                { }
            }
        }

        private void okButton_Click(object sender, EventArgs e)
        {
            if (saveSettings())
            {
                unsavedChanges = false;

                this.Close();
            }
        }

        private void resetAllButton_Click(object sender, EventArgs e)
        {
            DialogResult result = MessageBox.Show("Are you sure you want to reset all of the settings? You will have to re-select your backup path.", "Reset Settings", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
            if (result == DialogResult.Yes)
            {
				Properties.Settings.Default.Reset();
                Properties.Settings.Default.MapperSettings = new MapperSettings();
                //Properties.Settings.Default.Timestamps = Utility.GetPropertyDefaultValue<StringCollection>("Timestamps", true);
                /*foreach (System.Configuration.SettingsProperty prop in Properties.Settings.Default.Properties)
                {
                    if (prop.Name != "MapperSettings" && prop.Name != "Timestamps")
                    {
                        if (prop.PropertyType == typeof(int))
                            Properties.Settings.Default[prop.Name] = int.Parse((string)prop.DefaultValue);
                        else if (prop.PropertyType == typeof(bool))
                            Properties.Settings.Default[prop.Name] = bool.Parse((string)prop.DefaultValue);
                        else
                        Properties.Settings.Default[prop.Name] = prop.DefaultValue;
                        
                    }
                }*/

				Properties.Settings.Default.Save();

				Application.Restart();
            }
        }

        private void SettingsForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Alt && e.KeyCode == Keys.F4)
                e.Handled = true;
        }

        private bool saveSettings()
        {
            string text = "";
			Properties.Settings settings = Properties.Settings.Default;
            //validation checks

            #region General

            if (backupLocationTextBox.Text == "")
            {
                text = "Path to place backups is empty.\n";
            }
            if (minecraftPortableCheckbox.Checked && minecraftPortableTextBox.Text == "")
            {
                text += ".minecraft path is empty.\n";
            }

            if (exeLocationTextBox.Text != "" && !System.IO.File.Exists(exeLocationTextBox.Text))
            {
                text += "The Minecraft EXE path does not exist.\n";
            }
            if (mapperTextBox.Text != "" && !System.IO.File.Exists(mapperTextBox.Text))
            {
                text += "The Mapper path does not exist.";
            }
            
            if (text != "")
            {
                MessageBox.Show(text, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false; ;
            }

            if (!System.IO.Directory.Exists(backupLocationTextBox.Text))
            {
                if (MessageBox.Show("The path to place backups that you have selected does not exist. Do you want to create it?", "Path does not exists", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK)
                    System.IO.Directory.CreateDirectory(backupLocationTextBox.Text);
                else
                    return false;
            }
            #endregion

            //save settings

            #region General
			settings.EXEPath = exeLocationTextBox.Text;
			settings.BackupPath = backupLocationTextBox.Text;
			settings.MinecraftPortablePath = minecraftPortableCheckbox.Checked ? minecraftPortableTextBox.Text : "";
			settings.MapperPath = mapperTextBox.Text;
			settings.CheckForUpdates = updatesCheckBox.Checked;
			settings.SettingsEdited = true;
            #endregion

            #region Backup
			settings.ShouldZip = zipCheckBox.Checked;
			settings.ShouldMap = mapperCheckBox.Checked;
            if (backupsToKeepTextBox.Text == "")
                backupsToKeepTextBox.Text = "0";

			settings.NumberBackupsToKeep = int.Parse(backupsToKeepTextBox.Text);
            #endregion

            #region Timestamps
			settings.SelectedDateTimeFormat = (string)dateTimeFormatComboBox.SelectedItem;
			settings.Timestamps = timestamps;
            #endregion

            #region Mapper
			if (renderBlendedCheckBox.Enabled == true && renderBlendedCheckBox.Checked)
				settings.MapperSettings.CaveRenderingState = CaveRenderingState.Blended;
			else if (renderCavesCheckBox.Checked)
				settings.MapperSettings.CaveRenderingState = CaveRenderingState.Caves;
			else
				settings.MapperSettings.CaveRenderingState = CaveRenderingState.Disabled;

			if (northRadioButton.Checked)
				settings.MapperSettings.TopLeftDirection = Direction.North;
			else if (eastRadioButton.Checked)
				settings.MapperSettings.TopLeftDirection = Direction.East;
			else if (southRadioButton.Checked)
				settings.MapperSettings.TopLeftDirection = Direction.South;
			else if (westRadioButton.Checked)
				settings.MapperSettings.TopLeftDirection = Direction.West;

			settings.MapperSettings.Night = nightCheckBox.Checked;
			settings.MapperSettings.RenderSkylight = skylightCheckBox.Checked;
            #endregion

            if (mapperTextBox.Text == "" && mapperCheckBox.Checked)
            {
                MessageBox.Show("You have not selected a Mapper path. Mapper images will not be attached.");
                settings.ShouldMap = false;
            }

			Properties.Settings.Default.Save();

            if (this.SettingsUpdated != null)
            {
                this.SettingsUpdated();
            }

            return true;
        }
        
        private void cancelButton_Click(object sender, EventArgs e)
        {
            unsavedChanges = false;
            Properties.Settings.Default.Reload();
            Close();
        }

        #region General
        private void browseExeButton_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = Environment.SpecialFolder.MyComputer.ToString(); ;
            ofd.FileName = "Minecraft.exe";
            ofd.Title = "Choose your Minecraft EXE path";
            ofd.CheckFileExists = true;
            ofd.CheckPathExists = true;

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                exeLocationTextBox.Text = ofd.FileName;
                unsavedChanges = true;
            }
        }

        private void browseLocationBackupButton_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fdb = new FolderBrowserDialog();
            fdb.RootFolder = Environment.SpecialFolder.MyComputer;
            fdb.Description = "Choose your backup path";
            fdb.ShowNewFolderButton = true;

            if (fdb.ShowDialog() == DialogResult.OK)
            {
                backupLocationTextBox.Text = fdb.SelectedPath;
                unsavedChanges = true;
            }
        }

        private void minecraftPortableButton_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog fdb = new FolderBrowserDialog();
            fdb.RootFolder = Environment.SpecialFolder.MyComputer;
            fdb.Description = "Choose your .minecraft folder";

            if (fdb.ShowDialog() == DialogResult.OK)
            {
                minecraftPortableTextBox.Text = fdb.SelectedPath;
                unsavedChanges = true;
            }
        }

        private void browseMapperButton_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = Environment.SpecialFolder.MyComputer.ToString(); ;
            ofd.FileName = "Mapper.exe";
            ofd.Title = "Choose your Mapper path";
            ofd.CheckFileExists = true;
            ofd.CheckPathExists = true;

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                mapperTextBox.Text = ofd.FileName;
                mapperCheckBox.Checked = true;
                unsavedChanges = true;
            }
        }

        private void minecraftPortableCheckbox_CheckedChanged(object sender, EventArgs e)
        {
            bool isChecked = minecraftPortableCheckbox.Checked;
            minecraftPortableButton.Enabled = isChecked;
            minecraftPortableTextBox.Enabled = isChecked;
            unsavedChanges = true;
        }

        private void exeLocationTextBox_TextChanged(object sender, EventArgs e)
        {
            unsavedChanges = true;
        }

        private void mapperTextBox_TextChanged(object sender, EventArgs e)
        {
            unsavedChanges = true;
        }

        private void backupLocationTextBox_TextChanged(object sender, EventArgs e)
        {
            unsavedChanges = true;
        }

        private void minecraftPortableTextBox_TextChanged(object sender, EventArgs e)
        {
            unsavedChanges = true;
        }

        private void updatesCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            unsavedChanges = true;
        }
        #endregion

        #region Backup
        private void zipCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            unsavedChanges = true;
        }

        private void mapperCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            //if (Properties.Settings.Default.MapperPath == "" && mapperCheckBox.Checked)
            //{
            //    MessageBox.Show("You have not selected a Mapper path. Please go to the Global Settings form and select it.", "Path not selected", MessageBoxButtons.OK, MessageBoxIcon.Error);
            //    mapperCheckBox.Checked = false;

            //    return;
            //}

            unsavedChanges = true;
        }

        private void backupsToKeepTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (!char.IsDigit(e.KeyChar) && e.KeyChar != (char)Keys.Back)
                e.Handled = true;
            else
                unsavedChanges = true;
        }
        #endregion

        #region DateTimeFormat
        private void loadDateTimeFormatComboBox()
        {
            try
            {
                dateTimeFormatComboBox.Items.Clear();
                string[] array = timestamps.OfType<string>().ToArray();
                dateTimeFormatComboBox.Items.AddRange(Properties.Settings.Default.Timestamps.OfType<string>().ToArray());
                dateTimeFormatComboBox.SelectedItem = Properties.Settings.Default.SelectedDateTimeFormat;

                Utility.AdjustComboBoxWidth(dateTimeFormatComboBox);
            }
            catch (Exception e)
            { Utility.HandleError(e); }
        }

        #region Buttons
        private void yearButton_Click(object sender, EventArgs e)
        {
            addText("yyyy");
        }

        private void monthButton_Click(object sender, EventArgs e)
        {
            addText("MM");
        }

        private void dayButton_Click(object sender, EventArgs e)
        {
            addText("dd");
        }

        private void hoursButton_Click(object sender, EventArgs e)
        {
            addText("HH");
        }

        private void minutesButton_Click(object sender, EventArgs e)
        {
            addText("mm");
        }

        private void secondsButton_Click(object sender, EventArgs e)
        {
            addText("ss");
        }
        #endregion Buttons
        private void addText(string text)
        {
            dateTimeFormatTextBox.Text += text;
            dateTimeFormatTextBox.Select(); //put cursor on textbox
            dateTimeFormatTextBox.Select(dateTimeFormatTextBox.Text.Length, 0); //put cursor on end of the textbox and deselect
        }

        private void addButton_Click(object sender, EventArgs e)
        {
            timestamps.Add(dateTimeFormatTextBox.Text);
            dateTimeFormatComboBox.Items.Add(dateTimeFormatTextBox.Text);
            dateTimeFormatComboBox.SelectedIndex = dateTimeFormatComboBox.Items.Count - 1;
            dateTimeFormatTextBox.Clear();
            unsavedChanges = true;
        }

        private void dateTimeFormatTextBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            string letters = "\\ / . : * ? \"< > |";

            for (int i = 0; i < letters.Length; i++)
            {
                if (e.KeyChar != ' ' && e.KeyChar == letters[i])
                {
                    if (tip == null)
                        tip = new ToolTip();
                    tip.Show("The format cannot contain the letters " + letters, this, dateTimeFormatTextBox.Location.X, dateTimeFormatTextBox.Location.Y + 45, 5000);

                    e.Handled = true;
                    break;
                }
            }
        }

        private void resetButton_Click(object sender, EventArgs e)
        {
            //System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(System.Collections.Specialized.StringCollection));
            //System.IO.MemoryStream ms = new System.IO.MemoryStream(Encoding.Unicode.GetBytes((string)Properties.Settings.Default.Properties["Timestamps"].DefaultValue));
            //ms.Position = 0;
            //Properties.Settings.Default.Timestamps = (System.Collections.Specialized.StringCollection)xs.Deserialize(ms);
            Properties.Settings.Default.Timestamps = Utility.GetPropertyDefaultValue<System.Collections.Specialized.StringCollection>("Timestamps", true);
            Properties.Settings.Default.SelectedDateTimeFormat = (string)Properties.Settings.Default.Properties["SelectedDateTimeFormat"].DefaultValue;
            loadDateTimeFormatComboBox();
        }

        private void deleteButton_Click(object sender, EventArgs e)
        {
            if (dateTimeFormatComboBox.Items.Count > 1)
            {
                timestamps.Remove((string)dateTimeFormatComboBox.SelectedItem);
                int index = dateTimeFormatComboBox.SelectedIndex;
                dateTimeFormatComboBox.Items.Remove(dateTimeFormatComboBox.SelectedItem);
                if (index == 0) index = 1;
                dateTimeFormatComboBox.SelectedIndex = index - 1;
                unsavedChanges = true;
            }
            else
                MessageBox.Show("You need to have at least one timestamp.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        #endregion

        #region Mapper

        private void loadMapperSettings()
        {
            MapperSettings mapperSettings = Properties.Settings.Default.MapperSettings;

			switch (mapperSettings.CaveRenderingState)
            {
				case CaveRenderingState.Disabled:
					renderCavesCheckBox.Checked = false;
					renderBlendedCheckBox.Enabled = false;
					renderBlendedCheckBox.Checked = false;
					break;
				case CaveRenderingState.Blended:
					renderCavesCheckBox.Checked = true;
					renderBlendedCheckBox.Enabled = true;
					renderBlendedCheckBox.Checked = true;
					break;
				case CaveRenderingState.Caves:
					renderCavesCheckBox.Checked = true;
					renderBlendedCheckBox.Enabled = true;
					break;
            }

			switch (mapperSettings.TopLeftDirection)
			{
				case Direction.North:
					northRadioButton.Checked = true;
					break;
				case Direction.East:
					eastRadioButton.Checked = true;
					break;
				case Direction.South:
					southRadioButton.Checked = true;
					break;
				case Direction.West:
					westRadioButton.Checked = true;
					break;
			}

			nightCheckBox.Checked = mapperSettings.Night;
			skylightCheckBox.Checked = mapperSettings.RenderSkylight;
        }

        private void resetMapperButton_Click(object sender, EventArgs e)
        {
            Properties.Settings.Default.MapperSettings = new MapperSettings();
            unsavedChanges = true;
            loadMapperSettings();
        }
        #endregion

        private void SettingsForm_HelpButtonClicked(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (Enum.IsDefined(typeof(HelpTab), tabControl1.SelectedTab.Text))
            {
                HelpForm helpForm = new HelpForm((HelpTab)Enum.Parse(typeof(HelpTab), tabControl1.SelectedTab.Text));
                helpForm.ShowDialog();
            }
            else
            {
                HelpForm helpForm = new HelpForm(HelpTab.Backup);
                helpForm.ShowDialog();
            }
            e.Cancel = true;
        }
    }
}
